#include "stdafx.h"
#include <stdio.h>
#include <math.h>
#include "cv.h"
#include "highgui.h"
#include "graphicsUtility.h"


int gminGmax(IplImage *image,int *Gmin,int *Gmax,int percentualeMin,int percentualeMax){
	
	int min,max,j,i;
	int w,h,tot;
	int* isto;


	w = image->width;
	h = image->height;
	tot = w*h;
	*Gmin=0;
	*Gmax=255;

	min=(tot*percentualeMin)/100;
	max=(tot*percentualeMax)/100;
	
	isto=istogramma(image);

	i=0;

	for(j=0; j<256; j++){//scansiono l'istogramma
		i+=isto[j];
		if(i<=min) *Gmin=j;
		else if(i<=max) *Gmax=j;
	}

	return 0;
}




int gminGmax(IplImage *image,int *Gmin,int *Gmax,int percentualeMin,int percentualeMax,int w_iniziale,int w_finale,int h_iniziale,int h_finale){
	
	int min,max,j,i;
	int w,h,tot;
	int* isto;


	w = image->width;
	h = image->height;
	tot = (w_finale-w_iniziale)*(h_finale-h_iniziale);
	*Gmin=0;
	*Gmax=255;

	min=(tot*percentualeMin)/100;
	max=(tot*percentualeMax)/100;
	
	isto=istogramma(image,w_iniziale,w_finale,h_iniziale,h_finale);

	i=0;

	for(j=0; j<256; j++){//scansiono l'istogramma
		i+=isto[j];
		if(i<=min) *Gmin=j;
		else if(i<=max) *Gmax=j;
	}

	return 0;
}




IplImage* gammaCorrection(IplImage *image_in,double r){
	

	int w,ws,h;
	int i,j;
	double pixel;
	double potenza=1-r;
	IplImage* image_out;

	w = image_in->width;
	ws = image_in->widthStep;
	h = image_in->height;

	//alloco l'immagine di output 
	image_out=cvCreateImage(cvGetSize(image_in), IPL_DEPTH_8U, 1);

	//elaborazione
	for(j=0; j<h; j++){//scansiono le righe
		for(i=0; i<w; i++){//ad ogni riga, scansiono le colonne
			pixel=((unsigned char*)(image_in->imageData))[j*ws+i];
			((unsigned char*)((image_out)->imageData))[j*ws + i] = (unsigned char)(pow(255.0,potenza)*pow(pixel,r));  
			
		}
	}

	return image_out;
}


IplImage* stretching(IplImage *image_in,int percentualeMin,int percentualeMax){
	

	int Gmin=255;
	int	Gmax=0;
	int w,ws,h;
	int i,j;
	int pixel;
	IplImage* image_out;

	w = image_in->width;
	ws = image_in->widthStep;
	h = image_in->height;

	//alloco l'immagine di output 
	image_out=cvCreateImage(cvGetSize(image_in), IPL_DEPTH_8U, 1);

	//calcolo Gmin e Gmax
	gminGmax(image_in,&Gmin,&Gmax,percentualeMin,percentualeMax);

	double k=(double)255/((double)(Gmax-Gmin));

	//elaborazione
	for(j=0; j<h; j++){//scansiono le righe
		for(i=0; i<w; i++){//ad ogni riga, scansiono le colonne
			pixel=((unsigned char*)(image_in->imageData))[j*ws+i];
			if(pixel<Gmin) ((unsigned char*)((image_out)->imageData))[j*ws + i]=0;
			else if(pixel>Gmax) ((unsigned char*)((image_out)->imageData))[j*ws + i]=255;

			else ((unsigned char*)((image_out)->imageData))[j*ws + i] = (unsigned char)((pixel-Gmin)*k);  
			
		}
	}

	return image_out;
}




IplImage* equalizzazione(IplImage* image_in){

	int w,ws,h;
	int i,j,k;
	int pixel;
	int* isto;
	IplImage* image_out;
	
	w = image_in->width;
	ws = image_in->widthStep;
	h = image_in->height;

	//alloco l'immagine di output 
	image_out=cvCreateImage(cvGetSize(image_in), IPL_DEPTH_8U, 1);
	
	isto=istogramma(image_in);
	double costante=(double)(255.0/(h*w));

	//elaborazione
	for(j=0; j<h; j++){//scansiono le righe
		for(i=0; i<w; i++){//ad ogni riga, scansiono le colonne
			pixel=((unsigned char*)(image_in->imageData))[j*ws + i];
			int temp=0;

			for(k=0;k<pixel;k++){
				temp+=isto[k];
			}
			((unsigned char*)((image_out)->imageData))[j*ws + i]=(unsigned char)(costante*temp);

		}
	}

	return image_out;

}


IplImage* matching(IplImage* image_in,IplImage* image_campione){

	int w,ws,h;
	int i,j,k;
	int pixel;
	int* isto2;
	int isto3[256];
	int temp=0;
	int function[256];

	IplImage* image_out;

	w = image_in->width;
	ws = image_in->widthStep;
	h = image_in->height;

	//alloco l'immagine di output 
	
	isto2=istogramma(image_campione);

	double costante=(double)(255.0/(h*w));
	
	for(j=0;j<256;j++){
		function[j]=0;
		for(k=0;k<=j;k++){
			function[j]+=isto2[k];
		}
		function[j]=(int)(function[j]*costante);
	}

	for(j=0;j<256;j++){
		for(i=0;i<256;i++){
			if(function[i]==j){
				isto3[j]=i;
				temp=i;
				break;
			}
			if(i==255 && function[i]!=j){
				isto3[j]=temp;
			}
		}
	}

	image_out=equalizzazione(image_in);

	for(j=0; j<h; j++){//scansiono le righe
		for(i=0; i<w; i++){//ad ogni riga, scansiono le colonne
			pixel=((unsigned char*)(image_out->imageData))[j*ws + i];
			temp=isto3[pixel];
			((unsigned char*)((image_out)->imageData))[j*ws + i]=temp;

		}
	}

	return image_out;

}




IplImage* stretching(IplImage *image_in,int percentualeMin,int percentualeMax,int w_iniziale,int w_finale,int h_iniziale,int h_finale){
	

	int Gmin=255;
	int	Gmax=0;
	int w,ws,h;
	int i,j;
	int pixel;
	IplImage* image_out;

	w = image_in->width;
	ws = image_in->widthStep;
	h = image_in->height;

	//alloco l'immagine di output 
	image_out=cvCreateImage(cvGetSize(image_in), IPL_DEPTH_8U, 1);

	//calcolo Gmin e Gmax
	gminGmax(image_in,&Gmin,&Gmax,percentualeMin,percentualeMax,w_iniziale,w_finale,h_iniziale,h_finale);

	double k=(double)255/((double)(Gmax-Gmin));

	//elaborazione
	for(j=0; j<h; j++){//scansiono le righe
		for(i=0; i<w; i++){//ad ogni riga, scansiono le colonne
			pixel=((unsigned char*)(image_in->imageData))[j*ws+i];
			if(pixel<Gmin) ((unsigned char*)((image_out)->imageData))[j*ws + i]=0;
			else if(pixel>Gmax) ((unsigned char*)((image_out)->imageData))[j*ws + i]=255;

			else ((unsigned char*)((image_out)->imageData))[j*ws + i] = (unsigned char)((pixel-Gmin)*k);  
			
		}
	}

	return image_out;
}




unsigned char stretching(IplImage *image_in,int percentualeMin,int percentualeMax,int raggio,int x,int y){
	

	int Gmin=255;
	int	Gmax=0;
	int w,ws,h;
	int w_iniziale=y-raggio;
	int w_finale=y+raggio;
	int h_iniziale=x-raggio;
	int h_finale=x+raggio;
	
	unsigned char pixel;

	w = image_in->width;
	ws = image_in->widthStep;
	h = image_in->height;

	//calcolo Gmin e Gmax
	gminGmax(image_in,&Gmin,&Gmax,percentualeMin,percentualeMax,w_iniziale,w_finale,h_iniziale,h_finale);

	double k=(double)255/((double)(Gmax-Gmin));

	pixel=((unsigned char*)(image_in->imageData))[x*ws+y];
		if(pixel<Gmin) pixel=0;
		else if(pixel>Gmax) pixel=255;

		else pixel= (unsigned char)((pixel-Gmin)*k);  

	return pixel;
}




IplImage* equalizzazione(IplImage* image_in,int w_iniziale,int w_finale,int h_iniziale,int h_finale){

	int w,ws,h;
	int i,j,k;
	int pixel;
	int* isto;
	IplImage* image_out;
	
	w = image_in->width;
	ws = image_in->widthStep;
	h = image_in->height;

	//alloco l'immagine di output 
	image_out=cvCreateImage(cvGetSize(image_in), IPL_DEPTH_8U, 1);
	
	isto=istogramma(image_in,w_iniziale,w_finale,h_iniziale,h_finale);
	double costante=(double)(255.0/((h_finale-h_iniziale)*(w_finale-w_iniziale)));

	//elaborazione
	for(j=0; j<h; j++){//scansiono le righe
		for(i=0; i<w; i++){//ad ogni riga, scansiono le colonne
			pixel=((unsigned char*)(image_in->imageData))[j*ws + i];
			int temp=0;

			for(k=0;k<pixel;k++){
				temp+=isto[k];
			}
			((unsigned char*)((image_out)->imageData))[j*ws + i]=(unsigned char)(costante*temp);

		}
	}

	return image_out;

}


unsigned char equalizzazione(IplImage* image_in,int raggio,int x,int y){

	int w,ws,h;
	int k;
	int pixel;
	int* isto;
	int w_iniziale=y-raggio;
	int w_finale=y+raggio;
	int h_iniziale=x-raggio;
	int h_finale=x+raggio;
	
	w = image_in->width;
	ws = image_in->widthStep;
	h = image_in->height;

	isto=istogramma(image_in,w_iniziale,w_finale,h_iniziale,h_finale);
	double costante=(double)(255.0/((h_finale-h_iniziale)*(w_finale-w_iniziale)));

	//elaborazione
	pixel=((unsigned char*)(image_in->imageData))[x*ws + y];
		int temp=0;

		for(k=0;k<pixel;k++){
			temp+=isto[k];
		}
	return((unsigned char)(costante*temp));

}



IplImage* matching(IplImage* image_in,IplImage* image_campione,int w_iniziale,int w_finale,int h_iniziale,int h_finale){

	int w,ws,h;
	int i,j,k;
	int pixel;
	int* isto2;
	int isto3[256];
	int temp=0;
	int function[256];

	IplImage* image_out;

	w = image_in->width;
	ws = image_in->widthStep;
	h = image_in->height;

	//alloco l'immagine di output 
	
	isto2=istogramma(image_campione,w_iniziale,w_finale,h_iniziale,h_finale);

	double costante=(double)(255.0/(h*w));
	
	for(j=0;j<256;j++){
		function[j]=0;
		for(k=0;k<=j;k++){
			function[j]+=isto2[k];
		}
		function[j]=(int)(function[j]*costante);
	}

	for(j=0;j<256;j++){
		for(i=0;i<256;i++){
			if(function[i]==j){
				isto3[j]=i;
				temp=i;
				break;
			}
			if(i==255 && function[i]!=j){
				isto3[j]=temp;
			}
		}
	}

	image_out=equalizzazione(image_in);

	for(j=0; j<h; j++){//scansiono le righe
		for(i=0; i<w; i++){//ad ogni riga, scansiono le colonne
			pixel=((unsigned char*)(image_out->imageData))[j*ws + i];
			temp=isto3[pixel];
			((unsigned char*)((image_out)->imageData))[j*ws + i]=temp;

		}
	}

	return image_out;

}



unsigned char matching(IplImage* image_in,IplImage* image_campione,int raggio,int x,int y){

	int w,ws,h;
	int i,j,k;
	int pixel;
	int* isto2;
	int isto3[256];
	int temp=0;
	int function[256];
	int w_iniziale=y-raggio;
	int w_finale=y+raggio;
	int h_iniziale=x-raggio;
	int h_finale=x+raggio;

	IplImage* image_out;

	w = image_in->width;
	ws = image_in->widthStep;
	h = image_in->height;

	//alloco l'immagine di output 
	
	isto2=istogramma(image_campione,w_iniziale,w_finale,h_iniziale,h_finale);

	double costante=(double)(255.0/(h*w));
	
	for(j=0;j<256;j++){
		function[j]=0;
		for(k=0;k<=j;k++){
			function[j]+=isto2[k];
		}
		function[j]=(int)(function[j]*costante);
	}

	for(j=0;j<256;j++){
		for(i=0;i<256;i++){
			if(function[i]==j){
				isto3[j]=i;
				temp=i;
				break;
			}
			if(i==255 && function[i]!=j){
				isto3[j]=temp;
			}
		}
	}

	image_out=equalizzazione(image_in,w_iniziale,w_finale,h_iniziale,h_finale);

	pixel=((unsigned char*)(image_out->imageData))[x*ws + y];
	pixel=isto3[pixel];

	cvReleaseImage(&image_out);

	return pixel;

}




IplImage* istogramma_locale(IplImage* image_in,int w_iniziale,int w_finale,int h_iniziale,int h_finale,IplImage* image_campione){

	IplImage* image_out;

	image_out=matching(image_in,image_campione,w_iniziale,w_finale,h_iniziale,h_finale);
	
	return image_out;
}
unsigned char istogramma_locale(IplImage* image_in,int raggio,int x,int y,IplImage* image_campione){
	return matching(image_in,image_campione,raggio,x,y);
}
IplImage* istogramma_locale(IplImage* image_in,int w_iniziale,int w_finale,int h_iniziale,int h_finale,int percentualeMin,int percentualeMax){

	IplImage* image_out;

	image_out=stretching(image_in,percentualeMin,percentualeMax,w_iniziale,w_finale,h_iniziale,h_finale);
	
	return image_out;
}
unsigned char istogramma_locale(IplImage* image_in,int raggio,int x,int y,int percentualeMin,int percentualeMax){
	return stretching(image_in,percentualeMin,percentualeMax,raggio,x,y);
}
IplImage* istogramma_locale(IplImage* image_in,int w_iniziale,int w_finale,int h_iniziale,int h_finale){

	IplImage* image_out;

	image_out=equalizzazione(image_in,w_iniziale,w_finale,h_iniziale,h_finale);
	
	return image_out;
}





unsigned char istogramma_locale(IplImage* image_in,int raggio,int x,int y){

	return equalizzazione(image_in,raggio,x,y);
	
}





IplImage* sliding_windows_errato(IplImage* image_in,int num_windows_rows,int num_windows_columns){
	boolean terminated=FALSE;

	int w,ws,h;
	int i,j,k,m;
	int rows,columns;
	int w_iniziale=0,w_finale,h_iniziale=0,h_finale;
	int pixel;
	IplImage* image_out;
	IplImage* image_out_temp;
	
	
	w = image_in->width;
	ws = image_in->widthStep;
	h = image_in->height;

	rows=h/num_windows_rows+1;
	columns=w/num_windows_columns+1;

	//alloco l'immagine di output 
	image_out=cvCreateImage(cvGetSize(image_in), IPL_DEPTH_8U, 1);
	
	for(k=1;k<=num_windows_rows;k++){
		h_finale=k*rows;
		w_iniziale=0;
		if(h_finale>h)
			h_finale=h;
		for(m=1;m<=num_windows_columns;m++){
			w_finale=m*columns;
			if(w_finale>w)
				w_finale=w;
			image_out_temp=istogramma_locale(image_in,w_iniziale,w_finale,h_iniziale,h_finale);
			for(j=h_iniziale; j<h_finale; j++){//scansiono le righe
				for(i=w_iniziale; i<w_finale; i++){//ad ogni riga, scansiono le colonne
					pixel=((unsigned char*)(image_out_temp->imageData))[j*ws + i];
					((unsigned char*)((image_out)->imageData))[j*ws + i]=pixel;
				}
			}
			w_iniziale=w_finale+1;
		}
		h_iniziale=h_finale+1;
		
	}
	return image_out;
}

IplImage* sliding_windows_errato(IplImage* image_in,int num_windows_rows,int num_windows_columns,int percentualeMin,int percentualeMax){
	boolean terminated=FALSE;

	int w,ws,h;
	int i,j,k,m;
	int rows,columns;
	int w_iniziale=0,w_finale,h_iniziale=0,h_finale;
	int pixel;
	IplImage* image_out;
	IplImage* image_out_temp;
	
	
	w = image_in->width;
	ws = image_in->widthStep;
	h = image_in->height;

	rows=w/num_windows_rows+1;
	columns=h/num_windows_columns+1;

	//alloco l'immagine di output 
	image_out=cvCreateImage(cvGetSize(image_in), IPL_DEPTH_8U, 1);
	
	for(k=1;k<=rows;k++){
		h_finale=k*num_windows_rows;
		if(h_finale>h)
			h_finale=h;
		for(m=1;m<=columns;m++){
			w_finale=m*num_windows_columns;
			if(w_finale>w)
				w_finale=w;
			image_out_temp=istogramma_locale(image_in,w_iniziale,w_finale,h_iniziale,h_finale,percentualeMin,percentualeMax);
			for(j=h_iniziale; j<h_finale; j++){//scansiono le righe
				for(i=h_finale; i<w_finale; i++){//ad ogni riga, scansiono le colonne
					pixel=((unsigned char*)(image_out_temp->imageData))[j*ws + i];
					((unsigned char*)((image_out)->imageData))[j*ws + i]=pixel;
				}
			}
			w_iniziale=w_finale+1;
		}
		h_iniziale=h_finale+1;
		
	}
	return image_out;
}
IplImage* sliding_windows_errato(IplImage* image_in,int num_windows_rows,int num_windows_columns,IplImage* image_campione){
	boolean terminated=FALSE;

	int w,ws,h;
	int i,j,k,m;
	int rows,columns;
	int w_iniziale=0,w_finale,h_iniziale=0,h_finale;
	int pixel;
	IplImage* image_out;
	IplImage* image_out_temp;
	
	
	w = image_in->width;
	ws = image_in->widthStep;
	h = image_in->height;

	rows=w/num_windows_rows+1;
	columns=h/num_windows_columns+1;

	//alloco l'immagine di output 
	image_out=cvCreateImage(cvGetSize(image_in), IPL_DEPTH_8U, 1);
	
	for(k=1;k<=rows;k++){
		h_finale=k*num_windows_rows;
		if(h_finale>h)
			h_finale=h;
		for(m=1;m<=columns;m++){
			w_finale=m*num_windows_columns;
			if(w_finale>w)
				w_finale=w;
			image_out_temp=istogramma_locale(image_in,w_iniziale,w_finale,h_iniziale,h_finale,image_campione);
			for(j=h_iniziale; j<h_finale; j++){//scansiono le righe
				for(i=h_finale; i<w_finale; i++){//ad ogni riga, scansiono le colonne
					pixel=((unsigned char*)(image_out_temp->imageData))[j*ws + i];
					((unsigned char*)((image_out)->imageData))[j*ws + i]=pixel;
				}
			}
			w_iniziale=w_finale+1;
		}
		h_iniziale=h_finale+1;
		
	}
	return image_out;
}
IplImage* sliding_windows(IplImage* image_in,int raggio){


	int w,ws,h;
	int i,j;
	unsigned char pixel;
	IplImage* image_out;
	
	w = image_in->width;
	ws = image_in->widthStep;
	h = image_in->height;

	//alloco l'immagine di output 
	image_out=cvCreateImage(cvGetSize(image_in), IPL_DEPTH_8U, 1);
	
	for(j=0; j<h; j++){//scansiono le righe
		for(i=0; i<w; i++){//ad ogni riga, scansiono le colonne
			pixel=0;
			if(j<raggio || j>=h-raggio || i<raggio || i>=w-raggio){
			}
			else{
				pixel=istogramma_locale(image_in,raggio,j,i);
			}

			((unsigned char*)((image_out)->imageData))[j*ws + i] = pixel;	
		}
	}
	return image_out;
}
IplImage* sliding_windows(IplImage* image_in,int raggio,int percentualeMin,int percentualeMax){


	int w,ws,h;
	int i,j;
	unsigned char pixel;
	IplImage* image_out;
	
	w = image_in->width;
	ws = image_in->widthStep;
	h = image_in->height;

	//alloco l'immagine di output 
	image_out=cvCreateImage(cvGetSize(image_in), IPL_DEPTH_8U, 1);
	
	for(j=0; j<h; j++){//scansiono le righe
		for(i=0; i<w; i++){//ad ogni riga, scansiono le colonne
			pixel=0;
			if(j<raggio || j>=h-raggio || i<raggio || i>=w-raggio){
			}
			else{
				pixel=istogramma_locale(image_in,raggio,j,i,percentualeMin,percentualeMax);
			}

			((unsigned char*)((image_out)->imageData))[j*ws + i] = pixel;	
		}
	}
	return image_out;
}

IplImage* sliding_windows(IplImage* image_in,int raggio,IplImage* image_campione){

	int w,ws,h;
	int i,j;
	unsigned char pixel;
	IplImage* image_out;
	
	w = image_in->width;
	ws = image_in->widthStep;
	h = image_in->height;

	//alloco l'immagine di output 
	image_out=cvCreateImage(cvGetSize(image_in), IPL_DEPTH_8U, 1);
	
	for(j=0; j<h; j++){//scansiono le righe
		for(i=0; i<w; i++){//ad ogni riga, scansiono le colonne
			pixel=0;
			if(j<raggio || j>=h-raggio || i<raggio || i>=w-raggio){
			}
			else{
				pixel=istogramma_locale(image_in,raggio,j,i,image_campione);
			}

			((unsigned char*)((image_out)->imageData))[j*ws + i] = pixel;	
		}
	}
	return image_out;
}
